<!doctype html>
<html>
<head>
    <title>Upload File</title>
    <style>
        body { 
            font-family: Arial, sans-serif; 
            max-width: 600px; 
            margin: 50px auto; 
            padding: 20px; 
            background-color: #f5f5f5;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        .upload-option { 
            margin: 20px 0; 
            padding: 20px; 
            border: 1px solid #ddd; 
            border-radius: 8px; 
            background: #fafafa;
            transition: background-color 0.3s;
        }
        .upload-option:hover {
            background: #f0f0f0;
        }
        .upload-option h3 { 
            margin-top: 0; 
            color: #333;
            font-size: 1.2em;
        }
        input[type="file"] { 
            margin: 15px 0; 
            padding: 10px;
            border: 2px dashed #ccc;
            border-radius: 5px;
            width: 100%;
            box-sizing: border-box;
        }
        input[type="file"]:hover {
            border-color: #007cba;
        }
        input[type="submit"] { 
            background: #007cba; 
            color: white; 
            padding: 12px 25px; 
            border: none; 
            border-radius: 5px; 
            cursor: pointer; 
            font-size: 16px;
            transition: background-color 0.3s;
        }
        input[type="submit"]:hover { 
            background: #005a87; 
        }
        input[type="submit"]:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        .info-section {
            background: #e7f3ff;
            padding: 15px;
            border-radius: 5px;
            margin-top: 20px;
            border-left: 4px solid #007cba;
        }
        
        /* message style */
        .message {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 20px;
            border-radius: 5px;
            color: white;
            font-weight: bold;
            z-index: 1000;
            transform: translateX(400px);
            transition: transform 0.3s ease-in-out;
            max-width: 300px;
            word-wrap: break-word;
        }
        .message.show {
            transform: translateX(0);
        }
        .message.success {
            background: #4caf50;
        }
        .message.error {
            background: #f44336;
        }
        .message.warning {
            background: #ff9800;
        }
        
        /* loading state */
        .loading {
            display: none;
            text-align: center;
            margin: 10px 0;
            color: #007cba;
        }
        .spinner {
            border: 2px solid #f3f3f3;
            border-top: 2px solid #007cba;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            animation: spin 1s linear infinite;
            display: inline-block;
            margin-right: 10px;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        /* config editor style */
        .config-editor {
            width: 100%;
        }
        .config-toolbar {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            align-items: center;
        }
        .config-btn {
            background: #28a745;
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s;
        }
        .config-btn:hover {
            background: #218838;
        }
        .config-btn:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        .config-status {
            margin-left: auto;
            font-size: 14px;
            color: #666;
        }
        #configEditor {
            width: 100%;
            height: 400px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 15px;
            resize: vertical;
            background: #f8f9fa;
            box-sizing: border-box;
        }
        #configEditor:focus {
            outline: none;
            border-color: #007cba;
            background: white;
        }
        
        /* file manager style */
        .file-manager {
            width: 100%;
        }
        .file-toolbar {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            align-items: center;
        }
        .file-btn {
            background: #17a2b8;
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s;
        }
        .file-btn:hover {
            background: #138496;
        }
        .file-btn:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        .file-status {
            margin-left: auto;
            font-size: 14px;
            color: #666;
        }
        .file-list {
            border: 1px solid #ddd;
            border-radius: 5px;
            max-height: 400px;
            overflow-y: auto;
            background: white;
        }
        .file-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            border-bottom: 1px solid #eee;
            transition: background-color 0.2s;
        }
        .file-item:hover {
            background: #f8f9fa;
        }
        .file-item:last-child {
            border-bottom: none;
        }
        .file-icon {
            margin-right: 8px;
            font-size: 16px;
            min-width: 20px;
        }
        .file-info {
            flex: 1;
            min-width: 0;
        }
        .file-name {
            font-weight: 500;
            word-break: break-word;
        }
        .file-details {
            font-size: 12px;
            color: #666;
            margin-top: 2px;
        }
        .file-actions {
            display: flex;
            gap: 5px;
        }
        .file-action-btn {
            background: none;
            border: none;
            cursor: pointer;
            padding: 4px 8px;
            border-radius: 3px;
            font-size: 12px;
            transition: background-color 0.2s;
        }
        .file-action-btn:hover {
            background: #e9ecef;
        }
        .file-action-btn.delete:hover {
            background: #f8d7da;
            color: #721c24;
        }
        .file-children {
            margin-left: 20px;
        }
        .folder-toggle {
            background: none;
            border: none;
            cursor: pointer;
            padding: 0;
            margin-right: 5px;
            font-size: 12px;
        }
        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: #666;
        }
        
        /* shortcut style */
        kbd {
            background: #f8f9fa;
            border: 1px solid #ddd;
            border-radius: 3px;
            padding: 2px 6px;
            font-family: monospace;
            font-size: 12px;
            color: #333;
        }
    </style>
</head>
<body>
    <div class="container">
                    <h1>📁 File Management Tool</h1>
        

        
        <div class="upload-option">
            <h3>⚙️ Config Editor</h3>
            <div class="config-editor">
                <div class="config-toolbar">
                    <button id="loadConfig" class="config-btn">🔄 Load</button>
                    <button id="saveConfig" class="config-btn">💾 Save</button>
                    <button id="formatConfig" class="config-btn">🎨 Format</button>
                    <span id="configStatus" class="config-status"></span>
                </div>
                <textarea id="configEditor" placeholder="Config file will be displayed here..."></textarea>
                <div class="loading" id="configLoading">
                    <div class="spinner"></div>Processing...
                </div>
            </div>
        </div>
        
        <div class="upload-option">
            <h3>📁 File Manager</h3>
            <div class="file-manager">
                <div class="file-toolbar">
                    <button id="refreshFiles" class="file-btn">🔄 Refresh</button>
                    <button id="uploadFiles" class="file-btn">📤 Upload File</button>
                    <button id="uploadFolder" class="file-btn">📁 Upload Folder</button>
                    <input type="file" id="fileUpload" style="display: none;" multiple>
                    <input type="file" id="folderUpload" style="display: none;" webkitdirectory multiple>
                    <span id="fileStatus" class="file-status"></span>
                </div>
                <div class="file-list" id="fileList">
                    <div class="loading" id="fileLoading">
                        <div class="spinner"></div>Loading file list...
                    </div>
                </div>
            </div>
        </div>
        
        <div class="info-section">
            <p><strong>💡 Usage:</strong></p>
            <ul>
                <li><strong>Config Editor:</strong> Edit NssMPClib config file directly</li>
                <li><strong>File Manager:</strong> Upload, and delete protocol generation related data</li>
                <li><strong>Upload File:</strong> Support single or multiple file upload</li>
                <li><strong>Upload Folder:</strong> Keep the complete directory structure and upload the entire folder</li>
            </ul>
            <p><strong>🔧 Shortcuts:</strong></p>
            <ul>
                <li><kbd>Ctrl + S</kbd> - Save Config</li>
                <li><kbd>Ctrl + F</kbd> - Format JSON</li>
            </ul>
        </div>
    </div>

    <script>
        // show message
        function showMessage(text, type = 'success') {
            // remove existing message
            const existingMessage = document.querySelector('.message');
            if (existingMessage) {
                existingMessage.remove();
            }
            
            // create new message
            const message = document.createElement('div');
            message.className = `message ${type}`;
            message.textContent = text;
            document.body.appendChild(message);
            
            // show message
            setTimeout(() => message.classList.add('show'), 100);
            
            // auto hide message
            setTimeout(() => {
                message.classList.remove('show');
                setTimeout(() => message.remove(), 300);
            }, 4000);
        }
        
        // clear file selection
        function clearFileInput(inputId) {
            const input = document.getElementById(inputId);
            input.value = '';
            // trigger change event to update UI
            input.dispatchEvent(new Event('change'));
        }
        

        
        // ================== config editor functionality ==================
        
        const configEditor = document.getElementById('configEditor');
        const configStatus = document.getElementById('configStatus');
        const configLoading = document.getElementById('configLoading');
        
        // update status display
        function updateConfigStatus(text, type = 'info') {
            configStatus.textContent = text;
            configStatus.className = `config-status ${type}`;
            if (type === 'success') {
                configStatus.style.color = '#28a745';
            } else if (type === 'error') {
                configStatus.style.color = '#dc3545';
            } else {
                configStatus.style.color = '#666';
            }
        }
        
        // set loading state
        function setConfigLoading(loading) {
            configLoading.style.display = loading ? 'block' : 'none';
            document.getElementById('loadConfig').disabled = loading;
            document.getElementById('saveConfig').disabled = loading;
            document.getElementById('formatConfig').disabled = loading;
        }
        
        // load config file
        async function loadConfig() {
            setConfigLoading(true);
            updateConfigStatus('Loading config file...');
            
            try {
                const response = await fetch('/config', {
                    method: 'GET'
                });
                
                const result = await response.json();
                
                if (response.ok) {
                    configEditor.value = result.content;
                    updateConfigStatus('Config file loaded successfully', 'success');
                } else {
                    updateConfigStatus(result.error || 'Load failed', 'error');
                    showMessage(result.error || 'Load config file failed', 'error');
                }
            } catch (error) {
                updateConfigStatus('Network error', 'error');
                showMessage('Network error, please try again', 'error');
                console.error('Load config file error:', error);
            } finally {
                setConfigLoading(false);
            }
        }
        
        // save config file
        async function saveConfig() {
            const content = configEditor.value.trim();
            if (!content) {
                showMessage('Config content cannot be empty', 'error');
                return;
            }
            
            setConfigLoading(true);
            updateConfigStatus('Saving config file...');
            
            try {
                const response = await fetch('/config', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ content: content })
                });
                
                const result = await response.json();
                
                if (response.ok) {
                    updateConfigStatus('Config file saved successfully', 'success');
                    showMessage(result.message, 'success');
                } else {
                    updateConfigStatus(result.error || 'Save failed', 'error');
                    showMessage(result.error || 'Save config file failed', 'error');
                }
            } catch (error) {
                updateConfigStatus('Network error', 'error');
                showMessage('Network error, please try again', 'error');
                console.error('Save config file error:', error);
            } finally {
                setConfigLoading(false);
            }
        }
        
        // format JSON
        function formatConfig() {
            try {
                const content = configEditor.value.trim();
                if (!content) {
                    showMessage('No content to format', 'warning');
                    return;
                }
                
                const parsed = JSON.parse(content);
                const formatted = JSON.stringify(parsed, null, 4);
                configEditor.value = formatted;
                updateConfigStatus('JSON formatted successfully', 'success');
                showMessage('JSON formatted successfully', 'success');
            } catch (error) {
                updateConfigStatus('JSON format error', 'error');
                showMessage('JSON format error: ' + error.message, 'error');
            }
        }
        
        // bind config editor events
        document.getElementById('loadConfig').addEventListener('click', loadConfig);
        document.getElementById('saveConfig').addEventListener('click', saveConfig);
        document.getElementById('formatConfig').addEventListener('click', formatConfig);
        
        // load config file when page loads
        window.addEventListener('load', function() {
            setTimeout(loadConfig, 500); // delay 500ms to ensure page is fully rendered
        });
        
        // add shortcut support
        configEditor.addEventListener('keydown', function(e) {
            // Ctrl+S save
            if (e.ctrlKey && e.key === 's') {
                e.preventDefault();
                saveConfig();
            }
            // Ctrl+F format
            if (e.ctrlKey && e.key === 'f') {
                e.preventDefault();
                formatConfig();
            }
        });
        
        // ================== file manager functionality ==================
        
        const fileList = document.getElementById('fileList');
        const fileStatus = document.getElementById('fileStatus');
        const fileLoading = document.getElementById('fileLoading');
        const fileUpload = document.getElementById('fileUpload');
        const folderUpload = document.getElementById('folderUpload');
        
        // update file status display
        function updateFileStatus(text, type = 'info') {
            fileStatus.textContent = text;
            fileStatus.className = `file-status ${type}`;
            if (type === 'success') {
                fileStatus.style.color = '#28a745';
            } else if (type === 'error') {
                fileStatus.style.color = '#dc3545';
            } else {
                fileStatus.style.color = '#666';
            }
        }
        
        // set loading state
        function setFileLoading(loading) {
            fileLoading.style.display = loading ? 'block' : 'none';
            document.getElementById('refreshFiles').disabled = loading;
            document.getElementById('uploadFiles').disabled = loading;
            document.getElementById('uploadFolder').disabled = loading;
        }
        
        // format file size
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        // format time
        function formatTime(timestamp) {
            return new Date(timestamp * 1000).toLocaleString('zh-CN');
        }
        
        // get file icon
        function getFileIcon(item) {
            if (item.type === 'folder') {
                return '📁';
            }
            
            const ext = item.name.split('.').pop().toLowerCase();
            const iconMap = {
                'json': '📄',
                'txt': '📝',
                'py': '🐍',
                'js': '💛',
                'html': '🌐',
                'css': '🎨',
                'md': '📖',
                'pdf': '📕',
                'jpg': '🖼️',
                'png': '🖼️',
                'gif': '🖼️',
                'mp4': '🎬',
                'mp3': '🎵',
                'zip': '📦'
            };
            
            return iconMap[ext] || '📄';
        }
        
        // render file item
        function renderFileItem(item, level = 0) {
            const div = document.createElement('div');
            div.className = 'file-item';
            div.style.paddingLeft = `${12 + level * 20}px`;
            
            const icon = getFileIcon(item);
            const size = item.type === 'folder' ? `${item.children.length} items` : formatFileSize(item.size);
            const modified = formatTime(item.modified);
            
            div.innerHTML = `
                ${item.type === 'folder' ? `<button class="folder-toggle" data-path="${item.path}">▶</button>` : ''}
                <span class="file-icon">${icon}</span>
                <div class="file-info">
                    <div class="file-name">${item.name}</div>
                    <div class="file-details">${size} • ${modified}</div>
                </div>
                <div class="file-actions">
                    <button class="file-action-btn delete" onclick="deleteFile('${item.path}')">🗑️ Delete</button>
                </div>
            `;
            
            return div;
        }
        
        // recursively render file items and sub-items
        function renderFileItemRecursive(item, level = 0, container) {
            const itemElement = renderFileItem(item, level);
            container.appendChild(itemElement);
            
            // if it's a folder and has sub-items, recursively create sub-container
            if (item.type === 'folder' && item.children.length > 0) {
                const childrenContainer = document.createElement('div');
                childrenContainer.className = 'file-children';
                childrenContainer.style.display = 'none';
                childrenContainer.dataset.parent = item.path;
                
                // recursively render all sub-items
                item.children.forEach(child => {
                    renderFileItemRecursive(child, level + 1, childrenContainer);
                });
                
                container.appendChild(childrenContainer);
            }
        }
        
        // render file list
        function renderFileList(files, container = fileList) {
            container.innerHTML = '';
            
            if (!files || files.length === 0) {
                container.innerHTML = `
                    <div class="empty-state">
                        <div>📁</div>
                        <div>Directory is empty</div>
                        <div style="font-size: 12px; margin-top: 5px;">Upload some files to start using</div>
                    </div>
                `;
                return;
            }
            
            // recursively render all file items
            files.forEach(item => {
                renderFileItemRecursive(item, 0, container);
            });
            
            // use event delegation to handle all folder toggle events
            bindFolderToggleEvents(container);
        }
        
        // bind folder expand/collapse events (use event delegation)
        function bindFolderToggleEvents(container) {
            // remove old event listeners (if any)
            container.removeEventListener('click', handleFolderToggle);
            
            // use event delegation to handle all toggle button clicks
            container.addEventListener('click', handleFolderToggle);
        }
        
        // handle folder toggle event
        function handleFolderToggle(event) {
            // check if the clicked element is a folder-toggle button
            if (event.target.classList.contains('folder-toggle')) {
                event.stopPropagation(); // prevent event bubbling
                
                const toggle = event.target;
                const path = toggle.dataset.path;
                
                // find the corresponding children container in the entire file list
                const children = fileList.querySelector(`[data-parent="${path}"]`);
                
                if (children) {
                    const isHidden = children.style.display === 'none';
                    children.style.display = isHidden ? 'block' : 'none';
                    toggle.textContent = isHidden ? '▼' : '▶';
                }
            }
        }
        
        // load file list
        async function loadFiles() {
            setFileLoading(true);
            updateFileStatus('Loading file list...');
            
            try {
                const response = await fetch('/files', {
                    method: 'GET'
                });
                
                const result = await response.json();
                
                if (response.ok) {
                    renderFileList(result.files);
                    updateFileStatus(`${result.files.length} items`, 'success');
                } else {
                    updateFileStatus(result.error || 'Load failed', 'error');
                    showMessage(result.error || 'Load file list failed', 'error');
                }
            } catch (error) {
                updateFileStatus('Network error', 'error');
                showMessage('Network error, please try again', 'error');
                console.error('Load file list error:', error);
            } finally {
                setFileLoading(false);
            }
        }
        
        // delete file
        async function deleteFile(path) {
            if (!confirm(`Are you sure you want to delete "${path}"? This action cannot be undone.`)) {
                return;
            }
            
            try {
                const response = await fetch('/files', {
                    method: 'DELETE',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ path: path })
                });
                
                const result = await response.json();
                
                if (response.ok) {
                    showMessage(result.message, 'success');
                    loadFiles(); // reload file list
                } else {
                    showMessage(result.error || 'Delete failed', 'error');
                }
            } catch (error) {
                showMessage('Network error, please try again', 'error');
                console.error('Delete file error:', error);
            }
        }
        
        // upload file
        async function uploadFiles(files, isFolder = false) {
            if (!files || files.length === 0) return;
            
            const formData = new FormData();
            
            if (isFolder) {
                // folder upload
                formData.append('upload_type', 'folder');
                Array.from(files).forEach(file => {
                    formData.append('files', file);
                });
            } else {
                // file upload
                if (files.length === 1) {
                    formData.append('upload_type', 'file');
                    formData.append('file', files[0]);
                } else {
                    formData.append('upload_type', 'folder');
                    Array.from(files).forEach(file => {
                        formData.append('files', file);
                    });
                }
            }
            
            try {
                const response = await fetch('/upload', {
                    method: 'POST',
                    body: formData
                });
                
                const result = await response.json();
                
                if (response.ok) {
                    showMessage(result.message || `Successfully uploaded ${files.length} ${isFolder ? 'files' : 'file'}`, 'success');
                    
                    // if there are error messages, also show them
                    if (result.errors && result.errors.length > 0) {
                        setTimeout(() => {
                            showMessage(`Warning: ${result.errors.length} files have problems`, 'warning');
                        }, 1000);
                    }
                    
                    loadFiles(); // reload file list
                } else {
                    showMessage(result.error || 'Upload failed', 'error');
                }
            } catch (error) {
                showMessage('Network error, please try again', 'error');
                console.error('Upload file error:', error);
            }
        }
        
        // bind file manager events
        document.getElementById('refreshFiles').addEventListener('click', loadFiles);
        
        document.getElementById('uploadFiles').addEventListener('click', function() {
            fileUpload.click();
        });
        
        document.getElementById('uploadFolder').addEventListener('click', function() {
            folderUpload.click();
        });
        
        fileUpload.addEventListener('change', function(e) {
            if (e.target.files.length > 0) {
                uploadFiles(e.target.files, false);
                e.target.value = ''; // clear selection
            }
        });
        
        folderUpload.addEventListener('change', function(e) {
            if (e.target.files.length > 0) {
                uploadFiles(e.target.files, true);
                e.target.value = ''; // clear selection
            }
        });
        
        // load file list when page loads
        window.addEventListener('load', function() {
            setTimeout(loadFiles, 800); // delay 800ms to ensure config is loaded
        });
        
        // expose to global scope, for HTML inline events
        window.deleteFile = deleteFile;
    </script>
</body>
</html> 